home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / netmail / rnr214.zip / RNRPROC.PAS < prev    next >
Pascal/Delphi Source File  |  1996-02-04  |  36KB  |  1,492 lines

  1. unit rnrproc;
  2.  
  3. {
  4.  
  5. rnrproc.pas - rnr procedures
  6.  
  7. }
  8.  
  9. {$I rnr-def.pas}
  10.  
  11. interface
  12.  
  13. uses dos,crt,genericf,rnrglob,rnrconf,rnrfunc,rnrio,rnrfile,
  14.  rnrmous,rnrtime,exec;
  15.  
  16. var
  17.   execresult: integer;
  18.   execexitcode: integer;
  19.  
  20. procedure shutdown(exitcode: integer);
  21. procedure msgshutdown(msg: string; exitcode: integer);
  22. procedure warn(warning: string);
  23. procedure warn2(w1,w2: string);
  24. procedure warn3(w1,w2,w3: string);
  25. procedure warnerr(prg: string; doserr: integer);
  26. procedure execp(cmd,cmdline: string);
  27. procedure shellout;
  28. procedure unfoldergroup(var group: string);
  29. procedure pickasource(var trysource: string; var trysourcekind: sourcetype);
  30. procedure updatejoin(highestnum: articlefilenametype);
  31. procedure updatejoinunsubscribe;
  32. procedure updatejoinsubscribe(newgroup: string;
  33.  beforegroup: string; aftergroup: string);
  34. procedure addnewmailgroup(newgroup: string);
  35. procedure execviacomspec(cmdline: string);
  36. procedure notquiets(s: string);
  37. procedure notquietlns(s: string);
  38. procedure notquietlnss(s1,s2: string);
  39. procedure addalias(fromheader: string);
  40. procedure maybemkhier(dn: string);
  41. procedure appendencodedfile(destinationfn: string; includedfile: string);
  42. procedure waitnseconds(n: integer);
  43. procedure showaliases(asubstring: string);
  44. procedure showversion;
  45. procedure usershow(showline: string);
  46. procedure getexistingfilename(var afn: string; prompt: string; lastfn: string);
  47. procedure getfilename(var afn: string; prompt: string; lastfn: string);
  48.  
  49. implementation
  50.  
  51. procedure addtojoinedgroups(onegroup: string);
  52.  
  53. begin
  54.   if numjoined<maxjoined then
  55.     begin
  56.       inc(numjoined);
  57.       joinedgroups[numjoined] := onegroup;
  58.     end;
  59. end;
  60.  
  61. procedure shutdown;
  62.  
  63. begin
  64.   if joinfn<>'' then
  65.     close(joinf);
  66.   if haskillfile then
  67.     close(killf);
  68.   if hasantikillfile then
  69.     close(antikillf);
  70.  
  71.   mouseshutdown;
  72.  
  73.   xgotoxy(1,lpp);
  74.   xwriteln;
  75.  
  76.   if console then
  77.     begin
  78.       textattr := oldtextattr;
  79.       xwriteln;  {so it uses these new (original) colors for sure}
  80.     end;
  81.  
  82.   if quitmessage<>'' then
  83.     xwritelns(quitmessage);
  84.  
  85.   halt(exitcode);
  86. end;
  87.  
  88. procedure msgshutdown;
  89.  
  90. begin
  91.   quitmessage := msg;
  92.   shutdown(exitcode);
  93. end;
  94.  
  95. procedure warn;
  96.  
  97. var
  98.   wastec: char;
  99.  
  100. begin
  101.   xclreolxy(1,lpp);
  102.   xwritess(copy(warning,1,60),' - press any key ');
  103.   wastec := xreadkey;
  104.   xclreolxy(1,lpp);
  105. end;
  106.  
  107. procedure warn2;
  108.  
  109. begin
  110.   xwriteln;
  111.   xwriteln;
  112.   xclreolxy(1,lpp-2);
  113.   xclreolxy(1,lpp-1);
  114.   xwrites(w1);
  115.   warn(w2);
  116.   xclreolxy(1,lpp-2);
  117.   xclreolxy(1,lpp-1);
  118. end;
  119.  
  120. procedure warn3;
  121.  
  122. begin
  123.   xwriteln;
  124.   xwriteln;
  125.   xwriteln;
  126.   xclreolxy(1,lpp-3);
  127.   xclreolxy(1,lpp-2);
  128.   xwrites(w1);
  129.   xclreolxy(1,lpp-1);
  130.   xwrites(w2);
  131.   warn(w3);
  132.   xclreolxy(1,lpp-2);
  133.   xclreolxy(1,lpp-1);
  134. end;
  135.  
  136. procedure warnerr;
  137.  
  138. var
  139.   errstr: string;
  140.  
  141. begin
  142.   errstr := 'unknown #'+itoa(doserr); 
  143.  
  144.   if doserr=2 then errstr := '2 (file not found)'
  145.   else if doserr=3 then errstr := '3 (path not found)'
  146.   else if doserr=5 then errstr := '5 (access denied)'
  147.   else if doserr=6 then errstr := '6 (invalid handle)'
  148.   else if doserr=8 then errstr := '8 (not enough memory)'
  149.   else if doserr=10 then errstr := '10 (invalid environment)'
  150.   else if doserr=11 then errstr := '11 (invalid format)'
  151.   else if doserr=18 then errstr := '18 (no more files)';
  152.  
  153.   warn('warning: '+prg+' failed (error '+errstr+')');
  154. end;
  155.  
  156. procedure execp;
  157.  
  158. var
  159.   path: string;
  160.   foundapath: boolean;
  161.   execed: boolean;
  162.   ncmd: string;
  163.   nbase: string;
  164.   npath: string;
  165.   el: string;
  166.   at: integer;
  167.  
  168.     function indir(cmd,dir: string): boolean;
  169.  
  170.     var
  171.       fileinfo: searchrec;
  172.  
  173.     begin {indir}
  174.       findfirst(withbackslash(dir)+cmd,archive,fileinfo);
  175.       indir := (doserror=0);
  176.     end; {indir}
  177.  
  178.     procedure execswappable(pgm, cmdline: string);
  179.  
  180.     begin {execswappable}
  181.       if showdebug('exec') then
  182.         begin
  183.           xwriteln;
  184.           xwritesss('running:  pgm="',pgm,'", cmdline="');
  185.           xwritelnss(cmdline,'"');
  186.           xwriteln;
  187.         end;
  188.  
  189. {
  190.           $0000..00FF: The EXECed Program's return code
  191.           $0100:       Error writing swap file
  192.           $0200:       Program file not found
  193.           $03xx:       DOS-error-code xx calling EXEC
  194.           $0400:       Error allocating environment buffer
  195. }
  196.  
  197.       if swap='' then
  198.         execresult := do_exec(pgm, cmdline, 1, $ffff, false)
  199.       else if swap='ems' then
  200.         execresult := do_exec(pgm, cmdline, 1, $ffff, false)
  201.       else if swap='disk' then
  202.         execresult := do_exec(pgm, cmdline, -1, $ffff, false)
  203.       else if swap='no' then
  204.         begin
  205.           dos.exec(pgm, cmdline);
  206.           execresult := doserror;
  207.           if execresult=0 then
  208.             execresult := dosexitcode
  209.           else
  210.             execresult := $300+execresult;
  211.         end
  212.       else
  213.         begin
  214.           xwritelns('unknown swap parameter "'+swap+'", so not swapping');
  215.           dos.exec(pgm, cmdline);
  216.           execresult := doserror;
  217.           if execresult=0 then
  218.             execresult := dosexitcode
  219.           else
  220.             execresult := $300+execresult;
  221.         end;
  222.  
  223.       if showdebug('exec') then
  224.         begin
  225.           xwriteln;
  226.           xwritelnssss('back from:  ',pgm,' ',cmdline);
  227.           xwritelnsi('execresult=',execresult);
  228.         end;
  229.  
  230.       execexitcode := 0;
  231.       if (execresult and $ff00)=0 then
  232.         execexitcode := (execresult and $00ff);
  233.  
  234. { if there was no error running, return 0 }
  235. { if there was en error running, report it }
  236. { otherwise, just leave the error as is (256, 512, 1024 stick out) }
  237.  
  238.       if (execresult and $ff00)=0 then
  239.         execresult := 0
  240.       else if (execresult and $ff00)=3 then
  241.         execresult := (execresult and $00ff);
  242.  
  243.  
  244.     end; {execswappable}
  245.  
  246. begin
  247.   foundapath := false;
  248.   execed := false;
  249.  
  250.   ncmd := unslash(cmd);
  251.   nbase := ncmd;
  252.  
  253. {strip path from nbase}
  254.  
  255.   repeat
  256.     at := pos(':',nbase);
  257.     if at<>0 then
  258.       nbase := copy(nbase,at+1,255);
  259.   until at=0;
  260.  
  261.   repeat
  262.     at := pos('\',nbase);
  263.     if at<>0 then
  264.       nbase := copy(nbase,at+1,255);
  265.   until at=0;
  266.  
  267. {chop off path.  if trailing \, chop, unless root or drive:root (then add .)}
  268.  
  269.   npath := '';
  270.   if nbase<>ncmd then
  271.     begin
  272.       foundapath := true;  {so as to not look further than given path}
  273.       npath := copy(ncmd,1,length(ncmd)-length(nbase));
  274.  
  275.       if npath='\' then
  276.         npath := npath+'.';
  277.  
  278.       if right(npath,1)=':' then
  279.         npath := npath+'.';
  280.  
  281.       if pos(':\',npath)<>0 then
  282.         if copy(npath,length(npath)-1,2)=':\' then
  283.           npath := npath+'.';
  284.  
  285.       if copy(npath,length(npath),1)='\' then
  286.         npath := copy(npath,1,length(npath)-1);
  287.     end;
  288.  
  289. {if an explicit path, use it -- otherwise, just try '.'}
  290.  
  291.   if npath='' then
  292.     npath := '.';
  293.  
  294. {if no extension, try com then exe}
  295.  
  296.   if pos('.',nbase)=0 then
  297.     begin
  298.       if showdebug('exec') then
  299.         xwritelnssss('looking for ',nbase,'.com/.exe in ',npath);
  300.  
  301.       if indir(nbase+'.com',npath) then
  302.         begin
  303.           foundapath := true;
  304.           execed := true;
  305.           execswappable(withbackslash(npath)+nbase+'.com',cmdline);
  306.         end
  307.       else if indir(nbase+'.exe',npath) then
  308.         begin
  309.           foundapath := true;
  310.           execed := true;
  311.           execswappable(withbackslash(npath)+nbase+'.exe',cmdline);
  312.         end;
  313.     end
  314.   else if indir(nbase,npath) then
  315.     begin
  316.       foundapath := true;
  317.       execed := true;
  318.       execswappable(withbackslash(npath)+nbase,cmdline);
  319.     end;
  320.  
  321.   if not foundapath then
  322.     begin
  323.  
  324. {not found in explicit path (or ., if no explicit path).  try $PATH}
  325.  
  326.       path := getenv('PATH');
  327.       while not foundapath and (path<>'') do
  328.         begin
  329.           if copy(path,length(path),255)<>';' then
  330.             path := path+';';
  331.  
  332.           at := pos(';',path);
  333.           el := copy(path,1,at-1);
  334.           path := copy(path,at+1,255);
  335.  
  336.           if pos('.',nbase)=0 then
  337.             begin
  338.               if showdebug('exec') then
  339.                 xwritelnssss('looking for ',nbase,'.com/.exe in ',el);
  340.  
  341.               if indir(nbase+'.com',el) then
  342.                 begin
  343.                   foundapath := true;
  344.                   execed := true;
  345.                   execswappable(withbackslash(el)+nbase+'.com',cmdline);
  346.                 end
  347.               else if indir(nbase+'.exe',el) then
  348.                 begin
  349.                   foundapath := true;
  350.                   execed := true;
  351.                   execswappable(withbackslash(el)+nbase+'.exe',cmdline);
  352.                 end;
  353.             end
  354.           else
  355.             begin
  356.               if showdebug('exec') then
  357.                 xwritelnssss('looking for ',nbase,' in ',el);
  358.  
  359.               if indir(nbase,el) then
  360.                 begin
  361.                   foundapath := true;
  362.                   execed := true;
  363.                   execswappable(withbackslash(el)+nbase,cmdline);
  364.                 end;
  365.             end;
  366.         end;
  367.     end;
  368.  
  369.   if not execed then
  370.     begin
  371.       warn('could not exec '+cmd+' -- does it exist?');
  372.     end;
  373.  
  374. {$ifdef timeout}
  375.   resetidle;
  376. {$endif}
  377.  
  378. end;
  379.  
  380. procedure shellout;
  381.  
  382. var
  383.   wastec: char;
  384.  
  385. begin
  386.   if console and trusted then
  387.     begin
  388.       xgotoxy(1,lpp);
  389.       xwriteln;
  390.       xwriteln;
  391.       xwriteln;
  392.       xwritelns('use `EXIT'' to return to rnr');
  393.  
  394. {it is now impossible to not swap, but this wasn't always true}
  395.       if swap='' then
  396.         xwritelns('be careful - you do not have much memory available')
  397.       else
  398.         xwritelns(
  399.          'swapped -- you should have most memory available');
  400.  
  401.       xwriteln;
  402.       if comspec='' then
  403.         begin
  404.           warn('could not find what shell to run - no COMSPEC variable');
  405.         end
  406.       else
  407.         begin
  408.           mouseshutdown;
  409.           execp(comspec,'');
  410.           mouseinit;
  411.  
  412.           xgotoxy(1,lpp);
  413.           xwriteln;
  414.           xwriteln;
  415.           xwriteln;
  416.  
  417.           if execresult<>0 then
  418.             xwrites('(error) press any key to return to '+newsreadername+' ')
  419.           else
  420.             xwrites('press any key to return to '+newsreadername+' ');
  421.           wastec := xreadkey;
  422.  
  423.           xwrites(^M);
  424.           xclreol;
  425.  
  426.           if execresult<>0 then
  427.             warnerr('shell',execresult);
  428.         end
  429.     end;
  430. end;
  431.  
  432. procedure unfoldergroup;
  433.  
  434. begin
  435.   if length(group)>0 then
  436.     if group[1]='=' then
  437.       begin
  438.         if length(group)=1 then
  439.           group := mailprefix
  440.         else
  441.           group := mailprefix+'.'+copy(group,2,255);
  442.  
  443. { prevent possible security hole }
  444.  
  445.         if (numoccur('\',unslash(group))<>0) or
  446.          (numoccur(':',group)<>0) or
  447.          (pos('..',group)<>0) then
  448.           group := mailprefix;
  449.       end;
  450. end;
  451.  
  452. procedure pickasource;
  453.  
  454. const
  455.   baseprompt =
  456. {note:  line beyond 80 columns, only due to highlighting toggle chars}
  457. '{j}ump;{a}ll;{1}-{9} pgs;{#};{f}aq;{h}eader/{b}ody/{w}hole;{d}ate;{s}ubj/{n}ame/{e}ither;{+};{-}';
  458.  
  459. var
  460.   shouldsubscribe: char;
  461.   wheretoadd: char;
  462.   neargroup: string;
  463.   neargroupsourcekind: sourcetype;
  464.  
  465.   prompt: string;
  466.   howto: char;
  467.  
  468.   tempdate: string;
  469.  
  470. begin
  471.   xclreolxy(1,lpp);
  472.  
  473.   if trysource='' then
  474.     begin
  475.       xwrites('Goto group, group initials, or directory: ');
  476.       trysource := currsource;
  477.  
  478. { changed yespreserve to no - it was a pain having to hit ^U to cancel this }
  479.  
  480.       xreadlnse(trysource,cols-30,nopreserve,endkeyswithspace);
  481.  
  482. {mail folder support}
  483.  
  484.       unfoldergroup(trysource);
  485.     end;
  486.  
  487.   if trysource='' then
  488.     xclreolxy(1,lpp)
  489.   else
  490.     if not expandsource(trysource,trysourcekind) then
  491.       begin
  492.         if getgroupdir(trysource)='' then
  493.           begin
  494.             warn('could not find a group or directory to match');
  495.             trysource := '';
  496.           end
  497.         else
  498.           begin
  499.             wheretoadd := 'o';
  500.             neargroup := '';
  501.  
  502.             if not quiet then
  503.               begin
  504.                 xclreolxy(1,lpp-4);
  505.                 xclreolxy(1,lpp-3);
  506.                 xwrites('to "subscribe" is to add a group to your join file');
  507.                 xclreolxy(1,lpp-2);
  508.                 xwrites('which means it will be presented to you each time');
  509.                 xclreolxy(1,lpp-1);
  510.                 xwrites('you read news');
  511.               end;
  512.  
  513.             shouldsubscribe := onekeydef('subscribe?  {y}/{n}','yn','y');
  514.             xwrites(shouldsubscribe);
  515.  
  516.             if shouldsubscribe='n' then
  517.               trysource := '';
  518.  
  519.             if trysource<>'' then
  520.               begin
  521.                 wheretoadd := onekeydef(
  522.           '{^}beginning, {$}end, {-}before or {+}after some group, {o}ops',
  523.                  '^$-+o','$');
  524.                 xwrites(wheretoadd);
  525.                 if wheretoadd='o' then
  526.                   trysource := '';
  527.               end;
  528.  
  529.             if trysource<>'' then
  530.               begin
  531.                 if (wheretoadd='-') or (wheretoadd='+') then
  532.                   begin
  533.                     xclreolxy(1,lpp);
  534.                     if wheretoadd='-' then
  535.                       xwrites('before what group?  ')
  536.                     else
  537.                       xwrites('after what group?  ');
  538.  
  539.                     if currsourcekind=sourcegroup then
  540.                       neargroup := currsource;
  541.  
  542.                     xreadlnse(neargroup,cols-25,yespreserve,endkeyswithspace);
  543.                     if neargroup='' then
  544.                       trysource := ''
  545.                     else
  546.                       if not expandsource(neargroup,neargroupsourcekind) then
  547.                         begin
  548.                           warn('not joined to '+neargroup+
  549.                            ' either -- using beginning');
  550.                           wheretoadd := '^';
  551.                         end
  552.                       else if neargroupsourcekind<>sourcegroup then
  553.                         begin
  554.                           warn('not joined to '+neargroup+
  555.                            ' either -- using beginning');
  556.                           wheretoadd := '^';
  557.                         end;
  558.                   end;
  559.               end;
  560.  
  561. {
  562. due to special-casing in updatejoinsubscribe, could
  563. combine ^ with - and $ with +, but I hope this is more clear
  564. }
  565.  
  566.             if trysource<>'' then
  567.               begin
  568.                 xclreolxy(1,lpp);
  569.                 if wheretoadd='^' then
  570.                   updatejoinsubscribe(trysource,'','.not-at-end.')
  571.                 else if wheretoadd='$' then
  572.                   updatejoinsubscribe(trysource,'.not-at-begin.','')
  573.                 else if wheretoadd='-' then
  574.                   updatejoinsubscribe(trysource,neargroup,'.not-at-end.')
  575.                 else
  576.                   updatejoinsubscribe(trysource,'.not-at-begin',neargroup);
  577.  
  578.                 if not expandsource(trysource,trysourcekind) then
  579.                   begin
  580.                     warn('unable to add group!');
  581.                     trysource := '';
  582.                   end;
  583.               end;
  584.           end;
  585.       end;
  586.  
  587.   if trysource<>'' then
  588.     begin
  589.       xclreolxy(1,lpp-1);
  590.       xwritelnss('found source: ',trysource);
  591.  
  592.       if not quiet then
  593.         begin
  594.           xclreolxy(1,lpp-11);
  595.  
  596.           xclreolxy(1,lpp-10);
  597.         xwrites(sourcedesc(trysource,trysourcekind));
  598.  
  599.           xclreolxy(1,lpp-9);
  600.  
  601.           xclreolxy(1,lpp-8);
  602.         xwritehighlights(
  603.         '{j}ump to last position; {a}ll articles; {#} pick start article');
  604.  
  605.           xclreolxy(1,lpp-7);
  606.         xwritehighlights(
  607.         '{f}requently asked questions;'+
  608.         ' {h}eader,{b}ody,{w}hole-article searching');
  609.  
  610.           xclreolxy(1,lpp-6);
  611.         xwritehighlights(
  612.         '{+} no filtering due to `s''een, `k''ill, etc.; {d}ate range');
  613.  
  614.           xclreolxy(1,lpp-5);
  615.         xwritehighlights(
  616.         '{s}ubject, {n}ame, {e}ither (like {h}eaders, but faster)');
  617.  
  618.           xclreolxy(1,lpp-4);
  619.         xwritehighlights(
  620.         '{-} show antikilled only');
  621.  
  622.           xclreolxy(1,lpp-3);
  623.         xwritehighlights(
  624.         'remember, you can just hit {space} to start scanning normally');
  625.  
  626.           xclreolxy(1,lpp-2);
  627.         end;
  628.  
  629.       repeat
  630.  
  631.         prompt := '';
  632.  
  633.         if readunfiltered then
  634.           prompt := prompt+'+';
  635.  
  636.         if antikilledonly then
  637.           prompt := prompt+'-';
  638.  
  639.         if searchinheaders and searchinbody then
  640.           prompt := prompt+'w'
  641.         else if searchinheaders then
  642.           prompt := prompt+'h'
  643.         else if searchinbody then
  644.           prompt := prompt+'b';
  645.  
  646.         if searchthedate then
  647.           prompt := prompt+'d';
  648.  
  649.         if searchinsubj and searchinname then
  650.           prompt := prompt+'e'
  651.         else if searchinsubj then
  652.           prompt := prompt+'s'
  653.         else if searchinname then
  654.           prompt := prompt+'n';
  655.  
  656.         if prompt='' then
  657.           prompt := baseprompt
  658.         else
  659.           prompt := baseprompt+' '+prompt;
  660.  
  661.         howto := onekeydef(prompt,'ja123456789#hbw+-fdsne','j');
  662.  
  663.         if howto='+' then
  664.           readunfiltered := not readunfiltered;
  665.         if howto='-' then
  666.           antikilledonly := not antikilledonly;
  667.         if howto='h' then
  668.           searchinheaders := not searchinheaders;
  669.         if howto='b' then
  670.           searchinbody := not searchinbody;
  671.  
  672.         if howto='w' then  {I think this is the best way to toggle this}
  673.           begin
  674.             searchinheaders := not (searchinheaders or searchinbody);
  675.             searchinbody := searchinheaders;
  676.           end;
  677.  
  678.         if howto='d' then
  679.           searchthedate := not searchthedate;
  680.  
  681.         if howto='s' then
  682.           searchinsubj := not searchinsubj;
  683.         if howto='n' then
  684.           searchinname := not searchinname;
  685.         if howto='e' then
  686.           begin
  687.             searchinsubj := not (searchinsubj or searchinname);
  688.             searchinname := searchinsubj;
  689.           end;
  690.  
  691.         if searchinsubj or searchinname then
  692.           begin
  693.             searchinheaders := false;
  694.             searchinbody := false;
  695.           end;
  696.  
  697.       until (howto<>'+') and
  698.        (howto<>'-') and
  699.        (howto<>'w') and
  700.        (howto<>'h') and
  701.        (howto<>'b') and
  702.        (howto<>'d') and
  703.        (howto<>'n') and
  704.        (howto<>'s') and
  705.        (howto<>'e');
  706.  
  707. { setting it to impossiblylarge will automatically set it to current later }
  708.       lowestartsearched := impossiblylargeart;
  709.       readpagesback := 0;
  710.  
  711. { only groups are in the join file }
  712.       if trysourcekind<>sourcegroup then
  713.         lowestartsearched := 0;
  714.  
  715.       if howto='#' then
  716.         begin
  717.           xclreolxy(1,lpp);
  718.           xwrites('Start at article number (blank to ignore) ');
  719.           xreadlnse(prompt,cols-30,nopreserve,endkeyswithspace);
  720.           if prompt<>'' then
  721.             begin
  722.               lowestartsearched := atol(prompt);
  723.  
  724. { we really only search filenames numerically _above_ lowestartsearched }
  725.               if lowestartsearched<>0 then
  726.                 dec(lowestartsearched);
  727.  
  728.             end;
  729.         end;
  730.  
  731. { for `f' (FAQs), the searching is done for us with a cookie -- don't prompt }
  732.       if howto<>'f' then
  733.         if searchinheaders or
  734.          searchinbody or
  735.          searchinsubj or
  736.          searchinname then
  737.           begin
  738.             xclreolxy(1,lpp);
  739.             xwrites('Search for: ');
  740.             xreadlns(searchtext,cols-30,yespreserve);
  741.             if searchtext='' then
  742.               searchtext := newsreadername;
  743.           end;
  744.  
  745.       if howto='f' then  {now reset them to what we want}
  746.         begin
  747.           searchinheaders := true;
  748.           searchinbody := false;
  749.           searchinsubj := false;
  750.           searchinname := false;
  751.  
  752.           searchtext := faqcookie;
  753.           readunfiltered := true;
  754.           antikilledonly := false;
  755.           lowestartsearched := 0;
  756.         end;
  757.  
  758.       if searchthedate then
  759.         begin
  760.           if not quiet then
  761.             begin
  762.           xclreolxy(1,lpp-5);
  763.  
  764.           xclreolxy(1,lpp-4);
  765.         xwritehighlights(
  766.         'if you want no lower bound, use 1900-01-01');
  767.  
  768.           xclreolxy(1,lpp-3);
  769.         xwritehighlights(
  770.         'if you want no upper bound, use 2020-01-01 or something similar');
  771.  
  772.           xclreolxy(1,lpp-2);
  773.         end;
  774.  
  775.           xclreolxy(1,lpp);
  776.           xwrites('Date YYYY-MM-DD: earliest: ');
  777.  
  778.           tempdate := datetostring(searchdatelow);
  779.           xreadlns(tempdate,cols-30,yespreserve);
  780.           if tempdate='' then
  781.             tempdate := currentdatestring;
  782.           searchdatelow := ymdtodate(tempdate);
  783.  
  784.           xclreolxy(1,lpp);
  785.           xwrites('Date YYYY-MM-DD: latest: ');
  786.  
  787.           tempdate := datetostring(searchdatehigh);
  788.           xreadlns(tempdate,cols-30,yespreserve);
  789.           if tempdate='' then
  790.             tempdate := currentdatestring;
  791.           searchdatehigh := ymdtodate(tempdate);
  792.         end;
  793.  
  794.       if howto='a' then
  795.         lowestartsearched := 0;
  796.  
  797. { no join file for anything but groups }
  798.       if trysourcekind=sourcegroup then
  799.         if (howto>='1') and (howto<='9') then
  800.           readpagesback := ord(howto)-ord('0');
  801.  
  802.       xclreolxy(1,lpp);
  803.     end;
  804. end;
  805.  
  806. procedure updatejoin;
  807.  
  808. var
  809.   oldcurrsource: string;
  810.   groupline: string;
  811.   tempf: text;
  812.  
  813. begin
  814.   if currsourcekind=sourcegroup then
  815.     begin
  816.       oldcurrsource := currsource;
  817.  
  818.       if highestnum>alreadyread then
  819.         begin
  820.           if quiet then
  821.             xwritelns('Updating join file...')
  822.           else
  823.             xwritelnsss('Updating join file for ',currsource,'...');
  824.  
  825.           assign(tempf,withbackslash(temporarydir)+userid);
  826.           rewrite(tempf);
  827.  
  828.           reset(joinf);
  829.           while not eof(joinf) do
  830.             begin
  831.               readln(joinf,groupline);
  832.               if getfirstw(groupline)=currsource then
  833.                 writeln(tempf,currsource,' ',highestnum)
  834.               else
  835.                 writeln(tempf,groupline);
  836.             end;
  837.  
  838.           close(joinf);
  839.           close(tempf);
  840.  
  841.           reset(tempf);
  842.           rewrite(joinf);
  843.           while not eof(tempf) do
  844.             begin
  845.               readln(tempf,groupline);
  846.               writeln(joinf,groupline);
  847.             end;
  848.           close(tempf);
  849.           close(joinf);
  850.  
  851.           erase(tempf);
  852.  
  853.           reset(joinf);
  854.         end;
  855.  
  856.       currsource := oldcurrsource;
  857.     end;
  858. end;
  859.  
  860. procedure updatejoinunsubscribe;
  861.  
  862. var
  863.   groupline: string;
  864.   onegroup: string;
  865.   tempf: text;
  866.  
  867. begin
  868.   xwritelns('Updating join file...');
  869.  
  870.   assign(tempf,withbackslash(temporarydir)+userid);
  871.   rewrite(tempf);
  872.  
  873.   numjoined := 0;
  874.  
  875.   reset(joinf);
  876.   while not eof(joinf) do
  877.     begin
  878.       readln(joinf,groupline);
  879.       onegroup := getfirstw(groupline);
  880.       if onegroup<>currsource then
  881.         begin
  882.           addtojoinedgroups(onegroup);
  883.           writeln(tempf,groupline);
  884.         end;
  885.     end;
  886.  
  887.   close(joinf);
  888.   close(tempf);
  889.  
  890.   rewrite(joinf);
  891.   reset(tempf);
  892.   while not eof(tempf) do
  893.     begin
  894.       readln(tempf,groupline);
  895.       writeln(joinf,groupline);
  896.     end;
  897.   close(tempf);
  898.   close(joinf);
  899.  
  900.   erase(tempf);
  901.  
  902.   reset(joinf);
  903. end;
  904.  
  905. procedure updatejoinsubscribe;
  906.  
  907. var
  908.   added: boolean;
  909.  
  910.   tempf: text;
  911.  
  912.   groupline: string;
  913.   onegroup: string;
  914.  
  915. begin
  916.   added := false;
  917.  
  918.   xwritelns('Updating join file...');
  919.  
  920.   assign(tempf,withbackslash(temporarydir)+userid);
  921.   rewrite(tempf);
  922.  
  923.   numjoined := 0;
  924.  
  925.   reset(joinf);
  926.   while not eof(joinf) do
  927.     begin
  928.       readln(joinf,groupline);
  929.       onegroup := getfirstw(groupline);
  930.  
  931.       if not added then
  932.         begin
  933.           if (beforegroup='') and not ismailgroup(onegroup) then
  934.             begin
  935.               addtojoinedgroups(newgroup);
  936.               writeln(tempf,newgroup,' 0');
  937.               added := true;
  938.             end
  939.           else if beforegroup=onegroup then
  940.             begin
  941.               addtojoinedgroups(newgroup);
  942.               writeln(tempf,newgroup,' 0');
  943.               added := true;
  944.             end;
  945.         end;
  946.  
  947.       addtojoinedgroups(onegroup);
  948.       writeln(tempf,groupline);
  949.  
  950.       if not added then
  951.         begin
  952.           if aftergroup=onegroup then
  953.             begin
  954.               addtojoinedgroups(newgroup);
  955.               writeln(tempf,newgroup,' 0');
  956.               added := true;
  957.             end;
  958.         end;
  959.     end;
  960.  
  961.   if not added then
  962.     begin
  963.       addtojoinedgroups(newgroup);
  964.       writeln(tempf,newgroup,' 0');
  965.     end;
  966.  
  967.   close(joinf);
  968.   close(tempf);
  969.  
  970.   rewrite(joinf);
  971.   reset(tempf);
  972.   while not eof(tempf) do
  973.     begin
  974.       readln(tempf,groupline);
  975.       writeln(joinf,groupline);
  976.     end;
  977.   close(tempf);
  978.   close(joinf);
  979.  
  980.   erase(tempf);
  981.  
  982.   reset(joinf);
  983. end;
  984.  
  985. procedure addnewmailgroup;
  986.  
  987. var
  988.   added: boolean;
  989.   seenmailbutnotnew: boolean;
  990.   groupline: string;
  991.   onegroup: string;
  992.   tempf: text;
  993.  
  994. begin
  995.   added := false;
  996.  
  997.   seenmailbutnotnew := false;
  998.  
  999.   xwritelns('Updating join file...');
  1000.  
  1001.   assign(tempf,withbackslash(temporarydir)+userid);
  1002.   rewrite(tempf);
  1003.  
  1004.   numjoined := 0;
  1005.  
  1006.   reset(joinf);
  1007.   while not eof(joinf) do
  1008.     begin
  1009.       readln(joinf,groupline);
  1010.       onegroup := getfirstw(groupline);
  1011.  
  1012.       if onegroup=mailprefix then
  1013.         seenmailbutnotnew := true;
  1014.  
  1015. {insert the new group alphabetically in the mail groups, or after}
  1016. {the last one if it's the biggest alphabetically of them all}
  1017.  
  1018.       if (seenmailbutnotnew and not ismailgroup(onegroup)) or
  1019.        (ismailgroup(onegroup) and (onegroup>newgroup)) then
  1020.         if not added then
  1021.           begin
  1022.             added := true;
  1023.  
  1024.             addtojoinedgroups(newgroup);
  1025.             writeln(tempf,newgroup,' 0');
  1026.  
  1027.             seenmailbutnotnew := false;
  1028.           end;
  1029.  
  1030.       addtojoinedgroups(onegroup);
  1031.       writeln(tempf,groupline);
  1032.     end;
  1033.  
  1034.   if not added then
  1035.     begin
  1036.       addtojoinedgroups(newgroup);
  1037.       writeln(tempf,newgroup,' 0');
  1038.     end;
  1039.  
  1040.   close(joinf);
  1041.   close(tempf);
  1042.  
  1043.   rewrite(joinf);
  1044.   reset(tempf);
  1045.  
  1046.   while not eof(tempf) do
  1047.     begin
  1048.       readln(tempf,groupline);
  1049.       writeln(joinf,groupline);
  1050.     end;
  1051.  
  1052.   close(tempf);
  1053.   close(joinf);
  1054.  
  1055.   erase(tempf);
  1056.  
  1057.   reset(joinf);
  1058. end;
  1059.  
  1060. procedure execviacomspec;
  1061.  
  1062. {mouse shutdown already done, and init will be done soon after}
  1063.  
  1064. begin
  1065.   execp(comspec,'/c '+cmdline);
  1066. end;
  1067.  
  1068. procedure notquiets;
  1069.  
  1070. begin
  1071.   if not quiet then
  1072.     xwrites(s);
  1073. end;
  1074.  
  1075. procedure notquietlns;
  1076.  
  1077. begin
  1078.   if not quiet then
  1079.     xwritelns(s);
  1080. end;
  1081.  
  1082. procedure notquietlnss(s1,s2: string);
  1083.  
  1084. begin
  1085.   if not quiet then
  1086.     xwritelnss(s1,s2);
  1087. end;
  1088.  
  1089. procedure addalias;
  1090.  
  1091. {caller must refresh}
  1092.  
  1093. var
  1094.   aliasaddr: string;
  1095.   aliasname: string;
  1096.   aliasdest: char;
  1097.   aliasfn: string;
  1098.   aliasf: text;
  1099.  
  1100. begin
  1101.   xclreolxy(1,lpp);
  1102.  
  1103.   aliasaddr := getfromaddr(fromheader);
  1104.  
  1105.   xwrites('Address to add to aliases: ');
  1106.   xreadlnse(aliasaddr,50,yespreserve,endkeyswithspace);
  1107.  
  1108.   xclreolxy(1,lpp);
  1109.  
  1110.   if (aliasaddr<>'') then
  1111.     begin
  1112.       xwrites('local alias to use for that address: ');
  1113.       aliasname := lower(getfirstw(getfromname(fromheader)));
  1114.       xreadlnse(aliasname,cols-40,yespreserve,endkeyswithspace);
  1115.       xclreolxy(1,lpp);
  1116.  
  1117.       if aliasname<>'' then
  1118.         begin
  1119.           aliasdest := 'p';
  1120.           if trusted then
  1121.             begin
  1122.               aliasdest := onekeydef(
  1123.                '{p}ersonal or {s}ystem-wide alias, or {q}uit','psq','p');
  1124.             end
  1125.           else
  1126.             begin
  1127.               aliasdest := onekeydef(
  1128.                '{p}ersonal alias or {q}uit','pq','p');
  1129.             end;
  1130.  
  1131.           if not trusted then
  1132.             if aliasdest='s' then
  1133.               aliasdest := 'p';
  1134.  
  1135.           aliasfn := '';
  1136.  
  1137.           if aliasdest='p' then
  1138.             aliasfn := home+'\aliases'
  1139.           else if aliasdest='s' then
  1140.             begin
  1141.               if (xiface=ifacewaffle) or (xiface=ifaceuufree) then
  1142.                 aliasfn := configdir+'\system\'+'aliases'
  1143.               else if xiface=ifaceuupc then
  1144.                 aliasfn := unslash(getconfig('aliases'));
  1145.             end;
  1146.  
  1147.           if aliasfn<>'' then
  1148.             begin
  1149.               assign(aliasf,aliasfn);
  1150. {$I-}
  1151.               append(aliasf);
  1152. {$I+}
  1153.               if ioresult<>0 then
  1154. {$I-}
  1155.                 rewrite(aliasf);
  1156. {$I+}
  1157.  
  1158.               if ioresult=0 then
  1159.                 begin
  1160.                   writeln(aliasf,aliasname,' ',aliasaddr);
  1161.                   close(aliasf);
  1162.                 end
  1163.               else
  1164.                 warn('could not create '+aliasfn);
  1165.             end;
  1166.  
  1167.           xclreolxy(1,lpp);
  1168.  
  1169.         end;
  1170.     end;
  1171. end;
  1172.  
  1173. procedure maybemkhier;
  1174.  
  1175. var
  1176.   response: char;
  1177.  
  1178. begin
  1179.   if not dexists(dn) then
  1180.     begin
  1181.       if not trusted then
  1182.         begin
  1183.           xwritelnss(dn,' does not exist -- it must be created first');
  1184.           shutdown(1);
  1185.         end;
  1186.  
  1187.       response :=
  1188.        onekeydef(dn+' does not exist - create it? {y}/{N}','yNq','y');
  1189.  
  1190.       if response='y' then
  1191.         mkhier(dn);
  1192.  
  1193.       xclreolxy(1,lpp);
  1194.  
  1195.       if response='q' then
  1196.         shutdown(1);
  1197.     end;
  1198. end;
  1199.  
  1200. procedure appendencodedfile;
  1201.  
  1202. var
  1203.   destinationf: text;
  1204.   encodedfn: string;
  1205.   encodebarecmd: string;
  1206.   encodeparams: string;
  1207.   encodedf: text;
  1208.   encodedline: string;
  1209.  
  1210. begin
  1211.   encodedfn := withbackslash(temporarydir)+userid+'.enc';
  1212.  
  1213.   encodeparams := encodecommand;
  1214.   encodebarecmd := chopfirstw(encodeparams);
  1215.  
  1216.   if encodeparams<>'' then
  1217.     encodeparams := encodeparams+' ';
  1218.  
  1219.   encodeparams := encodeparams+includedfile+' '+encodedfn;
  1220.  
  1221.   xwriteln;
  1222.   xwritelns('encoding...');
  1223.  
  1224.   execp(encodebarecmd,encodeparams);
  1225. {}{}{}{} {check execresult!}
  1226.  
  1227.   assign(destinationf,destinationfn);
  1228.   append(destinationf);
  1229.  
  1230.   safereset(encodedf,encodedfn);
  1231.   if fileresult<>0 then
  1232.     writeln(destinationf,'encode failed for '+includedfile)
  1233.   else
  1234.     begin
  1235.       xwritelns('reading...');
  1236.  
  1237.       while not eof(encodedf) do
  1238.         begin
  1239.           readln(encodedf,encodedline);
  1240.           writeln(destinationf,encodedline);
  1241.         end;
  1242.       close(encodedf);
  1243.     end;
  1244.  
  1245.   close(destinationf);
  1246. end;
  1247.  
  1248. { assumes n<320 or so}
  1249. procedure waitnseconds;
  1250.  
  1251. var
  1252.   h,m,s,s00: word;
  1253.   olds, olds00: word;
  1254.   starting: word;
  1255.   s00towait: integer;
  1256.  
  1257. begin
  1258.   if n<320 then
  1259.     s00towait := n*100
  1260.   else
  1261.     s00towait := 32000;
  1262.  
  1263.   gettime(h,m,olds,olds00);
  1264.   s := olds;
  1265.   s00 := olds00;
  1266.  
  1267.   starting := olds*100+olds00;
  1268.  
  1269.   while (s*100+s00)<starting+s00towait do
  1270.     begin
  1271.       gettime(h,m,s,s00);
  1272.       if s<olds then
  1273.         dec(starting,6000);  {safer than inc(s,60) to allow for n>59}
  1274.     end;
  1275. end;
  1276.  
  1277. procedure showaliases(asubstring: string);
  1278.  
  1279. var
  1280.   aliasfn: string;
  1281.   currentline: integer;
  1282.   foundany: boolean;
  1283.  
  1284.   function showedaliasesin(aliasfn: string; asubstring: string): boolean;
  1285.  
  1286.   var
  1287.     result: boolean;
  1288.     aliasf: text;
  1289.     done: boolean;
  1290.     oneline: string;
  1291.     upsubstring: string;
  1292.  
  1293.   begin {showedaliasesin}
  1294.     result := false;
  1295.     upsubstring := upper(asubstring);
  1296.  
  1297.     safereset(aliasf,aliasfn);
  1298.     if fileresult=0 then
  1299.       begin
  1300.         done := false;
  1301.         while not done and not eof(aliasf) do
  1302.           begin
  1303.             readln(aliasf,oneline);
  1304.             if trim(oneline)<>'' then
  1305.               if (asubstring='') or textintext(upsubstring,upper(oneline)) then
  1306.                 begin
  1307.                   result := true;
  1308.                   xgotoxy(1,currentline);
  1309.                   xwrites(oneline);
  1310.  
  1311.                   inc(currentline);
  1312.                   if currentline>lpp-2 then
  1313.                     begin
  1314.                       done := true;
  1315.  
  1316.                       xclreolxy(1,currentline+1);
  1317.                       xclreolxy(1,currentline);
  1318.                       xwrites('(stopped at one screen)');
  1319.                     end;
  1320.                 end;
  1321.           end;
  1322.         close(aliasf);
  1323.       end;
  1324.  
  1325.     showedaliasesin := result;
  1326.   end; {showedaliasesin}
  1327.  
  1328. begin
  1329.   currentline := 2;
  1330.   foundany := false;
  1331.  
  1332.   xclrscr;
  1333.  
  1334.   if (xiface=ifacewaffle) or (xiface=ifaceuufree) then
  1335.     aliasfn := configdir+'\system\'+'aliases'
  1336.   else if xiface=ifaceuupc then
  1337.     aliasfn := unslash(getconfig('aliases'));
  1338.  
  1339.   if aliasfn<>'' then
  1340.     foundany := showedaliasesin(aliasfn,asubstring);
  1341.  
  1342.   if aliasfn<>home+'\aliases' then
  1343.     begin
  1344.       aliasfn := home+'\aliases';
  1345.       foundany := foundany or showedaliasesin(aliasfn,asubstring);
  1346.     end;
  1347.  
  1348.   if foundany then
  1349.     warn('done')
  1350.   else
  1351.     if asubstring='' then
  1352.       warn('no aliases')
  1353.     else
  1354.       warn('no aliases matched '+asubstring);
  1355. end;
  1356.  
  1357. procedure showversion;
  1358.  
  1359. begin
  1360.   warn2('',newsreadername+' '+newsreaderversion+', released '+releasedate);
  1361. end;
  1362.  
  1363. procedure usershow;
  1364.  
  1365. var
  1366.   mangledshowline: string;
  1367.   whattoshow: string;
  1368.   showparameters: string;
  1369.  
  1370. begin
  1371.   mangledshowline := ltrim(trim(showline));
  1372.   if mangledshowline='' then
  1373.     begin
  1374.       warn('show aliases [optional-substring], show time, show version');
  1375.     end
  1376.   else
  1377.     begin
  1378.       whattoshow := chopfirstw(mangledshowline);
  1379.       showparameters := mangledshowline;
  1380.       if partialmatch(whattoshow,'aliases','a') then
  1381.         begin
  1382.           showaliases(showparameters);
  1383.         end
  1384.       else if partialmatch(whattoshow,'time','t') then {remove this later}
  1385.         begin
  1386.           warn('it is now '+currentdatestring+' '+currenttimestring);
  1387.         end
  1388.       else if partialmatch(whattoshow,'version','v') then
  1389.         begin
  1390.           showversion;
  1391.         end
  1392.       else
  1393.         begin
  1394.           warn('unknown show object: '+whattoshow);
  1395.         end;
  1396.     end;
  1397. end;
  1398.  
  1399. procedure getexistingfilename;
  1400.  
  1401. var
  1402.   resultfn: string;
  1403.   resultf: text;
  1404.   findexistingfileparams: string;
  1405.   findexistingfilebarecmd: string;
  1406.  
  1407. begin
  1408.   if findexistingfilecommand=builtincookie then
  1409.     begin
  1410.       xclreolxy(1,lpp);
  1411.       xwritess(prompt,' ');
  1412.       afn := lastfn;
  1413.       xreadlnse(afn,cols-5-length(prompt),yespreserve,endkeyswithspace);
  1414.     end
  1415.   else
  1416.     begin
  1417.       resultfn := withbackslash(temporarydir)+userid+'.fil';
  1418.  
  1419.       findexistingfileparams := findexistingfilecommand;
  1420.       findexistingfilebarecmd := chopfirstw(findexistingfileparams);
  1421.  
  1422.       if findexistingfileparams<>'' then
  1423.         findexistingfileparams := findexistingfileparams+' ';
  1424.  
  1425.       findexistingfileparams := findexistingfileparams+resultfn;
  1426.  
  1427.       execp(findexistingfilebarecmd,findexistingfileparams);
  1428. {}{}{}{} {check execresult!}
  1429.  
  1430.       safereset(resultf,resultfn);
  1431.       if fileresult<>0 then
  1432.         warn('could not read '+resultfn)
  1433.       else
  1434.         begin
  1435.           if eof(resultf) then
  1436.             afn := ''
  1437.           else
  1438.             readln(resultf,afn);
  1439.  
  1440.           close(resultf);
  1441.         end;
  1442.     end;
  1443. end;
  1444.  
  1445. procedure getfilename;
  1446.  
  1447. var
  1448.   resultfn: string;
  1449.   resultf: text;
  1450.   findfileparams: string;
  1451.   findfilebarecmd: string;
  1452.  
  1453. begin
  1454.   if findfilecommand=builtincookie then
  1455.     begin
  1456.       xclreolxy(1,lpp);
  1457.       xwritess(prompt,' ');
  1458.       afn := lastfn;
  1459.       xreadlnse(afn,cols-5-length(prompt),yespreserve,endkeyswithspace);
  1460.     end
  1461.   else
  1462.     begin
  1463.       resultfn := withbackslash(temporarydir)+userid+'.fil';
  1464.  
  1465.       findfileparams := findfilecommand;
  1466.       findfilebarecmd := chopfirstw(findfileparams);
  1467.  
  1468.       if findfileparams<>'' then
  1469.         findfileparams := findfileparams+' ';
  1470.  
  1471.       findfileparams := findfileparams+resultfn;
  1472.  
  1473.       execp(findfilebarecmd,findfileparams);
  1474. {}{}{}{} {check execresult!}
  1475.  
  1476.       safereset(resultf,resultfn);
  1477.       if fileresult<>0 then
  1478.         warn('could not read '+resultfn)
  1479.       else
  1480.         begin
  1481.           if eof(resultf) then
  1482.             afn := ''
  1483.           else
  1484.             readln(resultf,afn);
  1485.  
  1486.           close(resultf);
  1487.         end;
  1488.     end;
  1489. end;
  1490.  
  1491. end.
  1492.